bitkeeper revision 1.858 (4075900bvZ22M6mUE2F3Vk8eDozqtw)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 8 Apr 2004 17:46:51 +0000 (17:46 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 8 Apr 2004 17:46:51 +0000 (17:46 +0000)
Add support for suspend/resume to new evtchn-IRQ binding mechanism.

xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c
xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c
xenolinux-2.4.25-sparse/include/asm-xen/irq.h

index a9c8991fb9f66d008a57aab6f924cb38674ae453..4f933057c278bef41aaa5fff4866bff711b62c15 100644 (file)
@@ -353,6 +353,69 @@ static struct irqaction misdirect_action = {
     NULL
 };
 
+void irq_suspend(void)
+{
+    evtchn_op_t op;
+    int         virq, irq, evtchn;
+
+    /* Unbind VIRQs from event channels. */
+    for ( virq = 0; virq < NR_VIRQS; virq++ )
+    {
+        if ( (irq = virq_to_irq[virq]) == -1 )
+            continue;
+        evtchn = irq_to_evtchn[irq];
+
+        /* Inform Xen that we are unbinding. */
+        op.cmd          = EVTCHNOP_close;
+        op.u.close.dom  = DOMID_SELF;
+        op.u.close.port = evtchn;
+        if ( HYPERVISOR_event_channel_op(&op) != 0 )
+            panic("Failed to unbind virtual IRQ %d\n", virq);
+
+        /* Mark the event channel as unused in our table. */
+        evtchn_to_irq[evtchn] = -1;
+        irq_to_evtchn[irq]    = -1;
+    }
+
+    /*
+     * We should now be unbound from all event channels. Stale bindings to 
+     * PIRQs and/or inter-domain event channels will cause us to barf here.
+     */
+    for ( evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++ )
+        if ( evtchn_to_irq[evtchn] != -1 )
+            panic("Suspend attempted while bound to evtchn %d.\n", evtchn);
+}
+
+
+void irq_resume(void)
+{
+    evtchn_op_t op;
+    int         virq, irq, evtchn;
+
+    for ( evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++ )
+        mask_evtchn(evtchn); /* New event-channel space is not 'live' yet. */
+
+    for ( virq = 0; virq < NR_VIRQS; virq++ )
+    {
+        if ( (irq = virq_to_irq[virq]) == -1 )
+            continue;
+
+        /* Get a new binding from Xen. */
+        op.cmd              = EVTCHNOP_bind_virq;
+        op.u.bind_virq.virq = virq;
+        if ( HYPERVISOR_event_channel_op(&op) != 0 )
+            panic("Failed to bind virtual IRQ %d\n", virq);
+        evtchn = op.u.bind_virq.port;
+        
+        /* Record the new mapping. */
+        evtchn_to_irq[evtchn] = irq;
+        irq_to_evtchn[irq]    = evtchn;
+
+        /* Ready for use. */
+        unmask_evtchn(evtchn);
+    }
+}
+
 void __init init_IRQ(void)
 {
     int i;
index 36faf5383220e4043c0af2e380fe39a03e032e7e..be7cc61efebc1c146bf04648b5f377d16e144a9a 100644 (file)
@@ -1190,6 +1190,8 @@ static void stop_task(void *unused)
 
     ctrl_if_suspend();
 
+    irq_suspend();
+
     HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
     clear_fixmap(FIX_SHARED_INFO);
 
@@ -1203,6 +1205,8 @@ static void stop_task(void *unused)
     HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
     memset(empty_zero_page, 0, PAGE_SIZE);
 
+    irq_resume();
+
     ctrl_if_resume();
 
     time_resume();
index a05b99640eccb8a6ca392c471dc1a766d4d0022e..668195e9ca400662c35a028e361a91ba9eb7c87c 100644 (file)
@@ -53,4 +53,7 @@ extern void disable_irq(unsigned int);
 extern void disable_irq_nosync(unsigned int);
 extern void enable_irq(unsigned int);
 
+extern void irq_suspend(void);
+extern void irq_resume(void);
+
 #endif /* _ASM_IRQ_H */